Nginx的rewrite应用

        Rewrite主要的功能是实现URL重写,Nginx 的 Rewrite 规则采用 PCRE Perl 兼容正则表达式的语法进行规则匹配,如相使用 Nginx 的 Rewrite 功能,在编译 Nginx 前要编译安装 PCRE 库。

一、Nginx使用if进行条件匹配

        Nginx可以用if进行条件匹配,语法规则类似C

1
if (条件){...} ( 可用于: server,location )

        检查一个条件是否符合,如果条件符合,则执行大括号内的语句。不支持嵌套,不支持多条件 && ||

        例如:if ($http_user_agent ~ MSIE) {rewrite ^(.*)$ /msie/$1 break;}

  1. 正则表达式匹配,其中:
  • ~ 为区分大小写匹配
  • ~* 为不区分大小写匹配
  • !~和!~*分别为区分大小写不匹配及不区分大小写不匹配
  1. 文件及目录匹配,其中:
  • -f和!-f用来判断是否存在文件
  • -d和!-d用来判断是否存在目录
  • -e和!-e用来判断是否存在文件或目录
  • -x和!-x用来判断文件是否可执行

        例如:if (!-f $request_filename) {proxy_pass http://127.0.0.1;}

        Wordpress的重定向规则:

1
if (!-e $request_filename) {rewrite ^/(index|atom|rsd)\.xml$ http://feed.shunz.net last;rewrite ^([_0-9a-zA-Z-]+)?(/wp-.*) $2 last;rewrite ^([_0-9a-zA-Z-]+)?(/.*\.php)$ $2 last;rewrite ^ /index.php last;}

        return ( 可用于: server,location,if ) ## 用于结束规则的执行并反回状态码给客户端。 状态码可以是 :204/400/402~406/408/410/411/413/416/500~504

        如:

1
2
3
location ~ .*\.(sh|bash)?$ {
return 403;
}

        访问的 URL 以 .sh .bash 结尾的,则返回 403 。

  • 204 No Content
  • 400 Bad Request
  • 402 Payment Required
  • 403 Forbidden
  • 404 Not Found
  • 405 Method Not Allowed
  • 406 Not Acceptable
  • 408 Request Timeout
  • 410 Gone
  • 411 Length Required
  • 413 Request Entity Too Large
  • 416 Requested Range Not Satisfiable
  • 500 Internal Server Error
  • 501 Not Implemented
  • 502 Bad Gateway
  • 503 Service Unavailable
  • 504 Gateway Timeout

二、Nginx使用rewrite

        rewrite ( 可用于: server,location,if ) ## 重写 URL ,或修改字符串。重写 URL 只对相对路径有效,如想对主机名,要使用 if 语句。

        例1:

1
2
3
4
if ($host ~* www\.(.*)) {
set $host_without_www $1;
rewrite ^(.*)$ http://$host_without_www$1 permanent;
}

        如果替换串以 http:// 开头,将会采用 301 或 302 跳转进行 URL 重定向。

        例2:

1
rewrite ^/feed/$ http://feed.shunz.net last;

        Nginx的Rewrite规则与Apache几乎完全一致,所不同的是最后的flag标记,Nginx的rewrite指令后支持的标记有last,break,redirect,permanent

  • last 相当于Apache里的[L]标记,表示完成rewrite,不再匹配后面的规则
  • break ( 可用于: server,location,if ) ## 本条规则匹配完成后,终止匹配,不再匹配后面的规则
    如:rewrite ^/b/(.*).html /play.php?video=$1 break;
  • redirect 返回302临时重定向,浏览器会显示跳转后的URL地址
  • permanent 返回301永久重定向,浏览器会显示跳转后的URL地址

        last/break用来实现URL重写,浏览器地址栏的URL不变,但在服务器端访问的路径发生了变化。

        redirect/permanent实现URL跳转,浏览器地址栏URL会显示跳转后的URL。

        使用 alias 指令时必须用 last 标记 ,使用 proxy_pass 指令时要用 break 表示。 last 标记在本条 rewrite 规则执行完毕后,会对其所在 server{….}标签重新发起请 求,而 break 标记则在本条规则匹配完成后,终止匹配。

        如:

1
2
3
4
location /cms/ {
proxy_pass http://test.abc.com;
rewrite "^/cms/(.*)\.html$" /cms/index.html break;
}

        这条规则如果使用 last 会导致死循环。

        一般在根 location 中(即 location / {….})或直接在 server 标签编写 rewrite 规则,推荐使用 last 标记,

        在非根 location 中 (即 location /cms/ {…}),则使用 break 标记。

Nginx $document_uri参数的使用

        $document_uri 表示访问的url 现在我的需求是,访问 www.abc.com 请求到 www.abc.com/abc/

        在nginx配置文件中加入

1
2
3
4
if ($document_uri !~ 'abc')
{
rewrite ^/(.*)$ http://www.abc.com/abc/$1 permanent;
}

        而不是单独加一句 rewrite ^/(.*)$ http://www.abc.com/abc/$1 permanent;

        如果只加rewrite 规则,而不限定条件,那么会造成死循环。 会访问到 http://www.abc.com/abc/abc/abc/abc/….